classdef app1_exported < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure             matlab.ui.Figure
        TextArea             matlab.ui.control.TextArea
        ButtonGroup          matlab.ui.container.ButtonGroup
        Button_3             matlab.ui.control.ToggleButton
        Button_4             matlab.ui.control.ToggleButton
        Label_2              matlab.ui.control.Label
        Knob                 matlab.ui.control.DiscreteKnob
        ButtonGroup_2        matlab.ui.container.ButtonGroup
        Button_5             matlab.ui.control.ToggleButton
        Button_6             matlab.ui.control.ToggleButton
        Label_3              matlab.ui.control.Label
        Knob_2               matlab.ui.control.DiscreteKnob
        Panel                matlab.ui.container.Panel
        Button_2             matlab.ui.control.Button
        Label                matlab.ui.control.Label
        Slider               matlab.ui.control.Slider
        LoadButton           matlab.ui.control.Button
        AngleEditFieldLabel  matlab.ui.control.Label
        AngleEditField       matlab.ui.control.NumericEditField
        rotateButton         matlab.ui.control.Button
        Panel_2              matlab.ui.container.Panel
        ImageAxes            matlab.ui.control.UIAxes
        ImageAxes_rotate     matlab.ui.control.UIAxes
        ImageAxes_denoise    matlab.ui.control.UIAxes
    end

    
    properties (Access = private)
        flag_noise = 0; % Description
        flag_filter; % Description
        imag_noise; % Description
    end
    
    methods (Access = public)
        
        function updateimage(app,imagefile)
            
            % For corn.tif, read the second image in the file 
            if strcmp(imagefile,'corn.tif')
                im_raw = imread('corn.tif', 2);
                im_raw = rgb2gray(im_raw);
            else
                try
                    im_raw = imread(imagefile);
                    if size(im_raw,3) > 1
                        im_raw = rgb2gray(im_raw);
                    end
            imwrite(im_raw,'myphoto.jpg');%这谁写的破玩意儿
                catch ME
                    % If problem reading image, display error message
                    uialert(app.UIFigure, ME.message, 'Image Error');
                    return;
                end            
            end
            
            imshow(im_raw,'Parent',app.ImageAxes);
%             switch size(im_raw,3)
%                 case 1
%                     % Display the grayscale image
%                     imagesc(app.ImageAxes,im_raw);
%                 case 3
%                     % Display the truecolor image
%                     imagesc(app.ImageAxes,im_raw);
%                 otherwise
%                     % Error when image is not grayscale or truecolor
%                     uialert(app.UIFigure, 'Image must be grayscale or truecolor.', 'Image Error');
%                     return;
%            end
        end
        
    end
    
    methods (Access = public)
        
        
        
        function rotate(app,imagefile)
             I = imread(imagefile);
            
            degree = app.AngleEditField.Value;
            I1=myimrotate(I,degree);     %调用myimrotate()函数旋转°
            
            function [ A ] = myimrotate(B,degree)                                 %定义旋转函数，degree为要旋转的角度
                [r,c,d]=size(B);                                                      %获取输入图像B的行r、列c和通道数d,为了旋转彩色图像所以有必要得到通道数d
                nH=round(r*abs(cosd(degree))+c*abs(sind(degree)));                    %旋转图像后得到的新高度，“round()函数四舍五入“
                nW=round(c*abs(cosd(degree))+r*abs(sind(degree)));                    %旋转图像后得到的新宽度
                A=zeros(nH,nW,d);                                                     %定义生成目标图像的行列以及通道数
                M1=[1 0 0;0 -1 0;-0.5*nW 0.5*nH 1 ];                                  %坐标系变换矩阵M1
                M2=[cosd(degree) -sind(degree) 0;sind(degree) cosd(degree) 0;0 0 1];  %角度旋转变换矩阵M2，我用的是顺时针方向
                M3=[1 0 0;0 -1 0;0.5*c 0.5*r 1];                                      %坐标系变换矩阵M3
                for i=1:nW
                    for j=1:nH
                        temp=[i j 1]*M1*M2*M3;                                    %得到旋转后的矩阵temp
                        y=temp(1,2);                                              %y取矩阵temp的第一行第二列,y对应j，为高度
                        x=temp(1,1);                                              %x取矩阵temp的第一行第一列,x对应i，为宽度
                        y=round(y);                                               %y四舍五入取整
                        x=round(x);                                               %x四舍五入取整
                        if(x>=1&&x<=c)&&(y>=1&&y<=r)                               %判断的得到的(x,y)点是否在原图像上
                            A(j,i,:)=B(y,x,:);                                     %将原图像的像素点赋值给对应的旋转后图像上的点
                        end                                                        %（”有人疑惑为啥不是A(i,j,:)=B(x,y,:);因为i,x对应的是列，即宽，而j,y对应的是行，即高“），我这里以x为横坐标，y为竖向纵坐标
                    end
                end
            end
            
            
            imshow(uint8(I1),'Parent',app.ImageAxes_rotate);
            %imagesc(app.ImageAxes_rotate,uint8(I1));
            %title('逆时针旋转 dgree °：I1');
        end
    end
    
    methods (Access = public)
        
        function histogram(app,imagefile)
            raw=imread(imagefile);
            size_raw = size(raw);
            
            % 计算原图直方图
            hist_array = zeros(1,256);
            x = 0:1:255;
            for i=1:size_raw(1)
                for j=1:size_raw(2)
                    hist_array(raw(i,j)+1) = hist_array(raw(i,j)+1)+1;
                end
            end
             
            % 图像均衡化
            norm_hist = hist_array/(size_raw(1)*size_raw(2));
            upper_tri = triu(ones(256));%生成一枚上三角矩阵
            Sk_array = round(norm_hist*upper_tri*255);
            
            for i=1:size_raw(1)
                for j=1:size_raw(2)
                    raw(i,j) = Sk_array(raw(i,j)+1);
                end
            end
 
            aa=uint8 (raw);  %将double型的矩阵aa变成图像的记录格式
            imshow(aa,'Parent',app.ImageAxes_rotate);
        end
    end
    
    methods (Access = public)
        
        function gama_tr(app,imagefile)
            
            %x=input('幂律指数：');%输入想要的调制的幂律指数 可直接用输入框
            x=app.Slider.Value;
%             I=imread('pout.tif'); %读入图片
            I = imread(imagefile);

            
            [h,w]=size(I);%获得原始图像的高h，宽w
            P=uint8(ones(h,w));%创建一个与原图像大小相同的背景，用于存放变换后的图像
            
            %进行伽马变换，当指数x小于1时，将较窄范围的暗输入值映射到较宽范围的输出值，指数x大于1时，情况相反。
            Q=double(I);
            P=Q.^x;
            P=uint8(P);
            
            imshow(P,'Parent',app.ImageAxes_rotate);
        end
    end
    
    methods (Access = private)
      
        function gaussian_Filter(app,imagefile)
            img = im2double(imread(imagefile));
            %% 加噪声
            [a,b] = size(img);
            img_noisy1 = imnoise(img,'gaussian',0,0.01);%高斯噪声
            img_noisy1=fft2(img_noisy1);%利用fft2()函数将图像从时域空间转换到频域空间
            img_noisy1=fftshift(img_noisy1);%将零频平移到中心位置
            [m,n]=size(img_noisy1);
            m_min=round(m/2);
            n_min=round(n/2);
            t_rf=img_noisy1;
            d_0=100;%设置阈值
            for i=1:m
                for j=1:n
                    d_1=sqrt((i-m_min)^2+(j-n_min)^2);
                    if(d_1>d_0)
                        x=0;
                    else
                        x=1.5; %增强
                    end
                    t_rf(i,j)=x*img_noisy1(i,j);
                end
            end
            t_rf=ifftshift(t_rf);
            t_rf=ifft2(t_rf);
            imshow(t_rf,'Parent',app.ImageAxes_rotate);
        end
        
        function saltpepper_Filter(app,imagefile)
            img = im2double(imread(imagefile));
            img_noisy1 = imnoise(img,'salt & pepper',0.05);%椒盐噪声
            img1 = img_noisy1;
            img_noisy1=fft2(img_noisy1);%利用fft2()函数将图像从时域空间转换到频域空间
            img_noisy1=fftshift(img_noisy1);%将零频平移到中心位置
            [m,n]=size(img_noisy1);
            m_min=round(m/2);
            n_min=round(n/2);
            t_rf=img_noisy1;
            d_0=100;%设置阈值
            for i=1:m
                for j=1:n
                    d_1=sqrt((i-m_min)^2+(j-n_min)^2);
                    if(d_1>d_0)
                        x=0;
                    else
                        x=1.5; %增强
                    end
                    t_rf(i,j)=x*img_noisy1(i,j);
                end
            end
            t_rf=ifftshift(t_rf);
            t_rf=ifft2(t_rf);
            imshow(t_rf,'Parent',app.ImageAxes_rotate);
        end
        
        function gaussian(app,imagefile,value)
            img = im2double(imread(imagefile));
            %% 加高斯噪声
            [a,b] = size(img);
            sigma =value;
            img1 = img + sqrt(sigma)*rand(a,b);
            imshow(img1,'Parent',app.ImageAxes_rotate);%显示原始图像
            app.imag_noise = img1;
        end
        
        function saltpepper(app,imagefile,value)
            img = im2double(imread(imagefile));
            %% 加椒盐噪声
            [a,b] = size(img);
            img1 = rand(a,b);
            sigma = value*2;
            img2 = img;
            img2(img1>=(1-0.5*sigma))=1;
            img2(img1<=(0.5*sigma))=0;
            img(img > img2)=0;
            img(img < img2)=1;
            imshow(img,'Parent',app.ImageAxes_rotate);%显示原始图像
            app.imag_noise = img;
        end
        
        function fredomainflitter(app,noiseimage,type)
            I=noiseimage;
            [m,n]=size(I);
            Do=0.1*m;
            F=fft2(I);
            u=0:(m-1);
            v=0:(n-1);
            idx=find(u>m/2);  %查找大于m/2元素的索引和值
            u(idx)=u(idx)-m;
            idy=find(v>n/2);
            v(idy)=v(idy)-n;
            [V,U]=meshgrid(v,u);  %使用向量v定义的坐标和向量u定义的坐标创建二维网络坐标
            D=sqrt(U.^2+V.^2);%%距离矩阵，表示频域中各个点（u，v）与频率矩形中心的距离
            
            way=type;
            %创建收集用户输入的对话框
            way=char(way);
            switch way
            case 'ILPF'
            H=double(D<=Do);%%理想低通滤波器 Ideal low-path filter
                            %若D<=Do，H=1（双精度），若D>=Do，H=0
            case 'BLPF'
            H=1./(1+(D./Do).^4);%%巴特沃斯低通滤波器butterworth low-path filter
            case 'GLPF'
            H=exp(-(D.^2)./(2*(Do^2)));%%高斯低通滤波器guassian high-path filter
            case 'IHPF'
            H=double(D>=Do);%%理想高通滤波器 Ideal low-path filter
            case 'BHPF'
            H=1./(1+(Do./D).^4);%%巴特沃斯高通滤波器butterworth low-path filter
            case 'GHPF'
            H=1-exp(-(D.^2)./(2*(Do^2)));%%高斯高通滤波器guassian high-path filter
            otherwise
            errordlg('听不懂你说啥,嚇嚇~');
            end
            
            Fout=F.*H;
            
%             imshow(log(fftshift(abs(Fout))+1),[]),title('滤波后图像的频谱图');
                                                  %abs取绝对值或复数的模
                                                  %fftshift将零频分量移到频谱中心
            f=real(ifft2(Fout));    %逆傅里叶变换
%             f=uint8(f);
%             subplot(132),imshow(f);
            imshow(f,'Parent',app.ImageAxes_denoise);
            
        end
    end
    

    % Callbacks that handle component events
    methods (Access = private)

        % Button pushed function: LoadButton
        function LoadButtonPushed(app, event)
            filterspec = {'*.jpg;*.tif;*.png;*.gif','All Image Files'};
            [f, p] = uigetfile(filterspec);
            %formatSpec = uigetfile;
            %fprintf(formatSpec)
            % Make sure user didn't cancel uigetfile dialog
            if (ischar(p))
               fname = [p f];
               updateimage(app, fname);
            end
        end

        % Button pushed function: rotateButton
        function rotateButtonPushed(app, event)
            rotate(app,'myphoto.jpg');
        end

        % Button pushed function: Button_2
        function Button_2Pushed(app, event)
           histogram(app,'myphoto.jpg') 
        end

        % Value changed function: Slider
        function SliderValueChanged(app, event)
           % value = im2double(app.Slider.Value);
            gama_tr(app,'myphoto.jpg')
        end

        % Callback function
        function gaosiButtonPushed(app, event)
            gaussian(app,'myphoto.jpg')
        end

        % Callback function
        function gaosi_quzaoButtonPushed(app, event)
            gaussian_Filter(app,'myphoto.jpg')
        end

        % Callback function
        function jiaoyanButtonPushed(app, event)
            saltpepper(app,'myphoto.jpg')
        end

        % Callback function
        function jiaoyan_quzaoButtonPushed(app, event)
            saltpepper_Filter(app,'myphoto.jpg')
        end

        % Selection changed function: ButtonGroup
        function ButtonGroupSelectionChanged(app, event)
            selectedButton = app.ButtonGroup.SelectedObject;
            switch selectedButton
                case app.Button_3
                    app.flag_noise = 1;
                case app.Button_4
                    app.flag_noise = 2;
            end
        end

        % Value changed function: Knob
        function KnobValueChanged(app, event)
            value = app.Knob.Value;
            switch app.flag_noise
                case 1
                    gaussian(app,'myphoto.jpg',value);
                case 2
                    saltpepper(app,'myphoto.jpg',value);
            end
            
         
        end

        % Selection changed function: ButtonGroup_2
        function ButtonGroup_2SelectionChanged(app, event)
            selectedButton = app.ButtonGroup_2.SelectedObject;
            switch selectedButton
                case app.Button_5
                    app.flag_filter = 1;
                case app.Button_6
                    app.flag_filter = 2;
            end
        end

        % Value changed function: Knob_2
        function Knob_2ValueChanged(app, event)
            value = app.Knob_2.Value;
            switch app.flag_filter
                case 1
                    value = strrep(value,'_','L');
                    fredomainflitter(app,app.imag_noise,value);
                case 2
                    value = strrep(value,'_','H');
                    fredomainflitter(app,app.imag_noise,value);
            end
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create UIFigure and hide until all components are created
            app.UIFigure = uifigure('Visible', 'off');
            app.UIFigure.Position = [100 100 920 612];
            app.UIFigure.Name = 'MATLAB App';

            % Create TextArea
            app.TextArea = uitextarea(app.UIFigure);
            app.TextArea.HorizontalAlignment = 'center';
            app.TextArea.FontName = 'Arial';
            app.TextArea.FontWeight = 'bold';
            app.TextArea.BackgroundColor = [0 0.4471 0.7412];
            app.TextArea.Position = [1 589 217 24];
            app.TextArea.Value = {'GUI of Digital Image Processing'};

            % Create ButtonGroup
            app.ButtonGroup = uibuttongroup(app.UIFigure);
            app.ButtonGroup.SelectionChangedFcn = createCallbackFcn(app, @ButtonGroupSelectionChanged, true);
            app.ButtonGroup.ForegroundColor = [0 0.4471 0.7412];
            app.ButtonGroup.Title = '图像加噪';
            app.ButtonGroup.BackgroundColor = [0.8 0.8 0.8];
            app.ButtonGroup.FontWeight = 'bold';
            app.ButtonGroup.Position = [307 167 308 128];

            % Create Button_3
            app.Button_3 = uitogglebutton(app.ButtonGroup);
            app.Button_3.Text = '高斯噪声';
            app.Button_3.BackgroundColor = [1 1 1];
            app.Button_3.Position = [14 60 112 34];

            % Create Button_4
            app.Button_4 = uitogglebutton(app.ButtonGroup);
            app.Button_4.Text = '椒盐噪声';
            app.Button_4.BackgroundColor = [0.149 0.149 0.149];
            app.Button_4.FontColor = [1 1 1];
            app.Button_4.Position = [14 17 112 31];
            app.Button_4.Value = true;

            % Create Label_2
            app.Label_2 = uilabel(app.ButtonGroup);
            app.Label_2.HorizontalAlignment = 'center';
            app.Label_2.Position = [199 1 53 22];
            app.Label_2.Text = '噪声指标';

            % Create Knob
            app.Knob = uiknob(app.ButtonGroup, 'discrete');
            app.Knob.ItemsData = [0 0.01 0.03 0.05];
            app.Knob.ValueChangedFcn = createCallbackFcn(app, @KnobValueChanged, true);
            app.Knob.Position = [196 26 60 60];
            app.Knob.Value = 0;

            % Create ButtonGroup_2
            app.ButtonGroup_2 = uibuttongroup(app.UIFigure);
            app.ButtonGroup_2.SelectionChangedFcn = createCallbackFcn(app, @ButtonGroup_2SelectionChanged, true);
            app.ButtonGroup_2.ForegroundColor = [0 0.4471 0.7412];
            app.ButtonGroup_2.Title = '频域滤波';
            app.ButtonGroup_2.BackgroundColor = [0.8 0.8 0.8];
            app.ButtonGroup_2.FontWeight = 'bold';
            app.ButtonGroup_2.Position = [307 11 308 124];

            % Create Button_5
            app.Button_5 = uitogglebutton(app.ButtonGroup_2);
            app.Button_5.Text = '低通滤波';
            app.Button_5.BackgroundColor = [1 1 1];
            app.Button_5.Position = [14 54 112 34];

            % Create Button_6
            app.Button_6 = uitogglebutton(app.ButtonGroup_2);
            app.Button_6.Text = '高通滤波';
            app.Button_6.BackgroundColor = [0.149 0.149 0.149];
            app.Button_6.FontColor = [1 1 1];
            app.Button_6.Position = [14 14 112 31];
            app.Button_6.Value = true;

            % Create Label_3
            app.Label_3 = uilabel(app.ButtonGroup_2);
            app.Label_3.HorizontalAlignment = 'center';
            app.Label_3.Position = [197 -1 65 22];
            app.Label_3.Text = '滤波器种类';

            % Create Knob_2
            app.Knob_2 = uiknob(app.ButtonGroup_2, 'discrete');
            app.Knob_2.Items = {'I_PF', 'B_PF', 'G_PF'};
            app.Knob_2.ValueChangedFcn = createCallbackFcn(app, @Knob_2ValueChanged, true);
            app.Knob_2.Position = [196 20 60 60];
            app.Knob_2.Value = 'I_PF';

            % Create Panel
            app.Panel = uipanel(app.UIFigure);
            app.Panel.ForegroundColor = [0 0.4471 0.7412];
            app.Panel.Title = '基础功能';
            app.Panel.BackgroundColor = [0.8 0.8 0.8];
            app.Panel.FontWeight = 'bold';
            app.Panel.Position = [15 42 274 224];

            % Create Button_2
            app.Button_2 = uibutton(app.Panel, 'push');
            app.Button_2.ButtonPushedFcn = createCallbackFcn(app, @Button_2Pushed, true);
            app.Button_2.FontSize = 16;
            app.Button_2.FontWeight = 'bold';
            app.Button_2.Position = [146 148 113 42];
            app.Button_2.Text = {'直方图均衡化'; ''};

            % Create Label
            app.Label = uilabel(app.Panel);
            app.Label.HorizontalAlignment = 'right';
            app.Label.FontSize = 16;
            app.Label.Position = [8 23 69 22];
            app.Label.Text = '伽玛变换';

            % Create Slider
            app.Slider = uislider(app.Panel);
            app.Slider.Limits = [0.7 1.3];
            app.Slider.ValueChangedFcn = createCallbackFcn(app, @SliderValueChanged, true);
            app.Slider.Position = [91 43 164 7];
            app.Slider.Value = 0.7;

            % Create LoadButton
            app.LoadButton = uibutton(app.Panel, 'push');
            app.LoadButton.ButtonPushedFcn = createCallbackFcn(app, @LoadButtonPushed, true);
            app.LoadButton.FontSize = 16;
            app.LoadButton.FontWeight = 'bold';
            app.LoadButton.Position = [11 148 100 42];
            app.LoadButton.Text = '加载图像';

            % Create AngleEditFieldLabel
            app.AngleEditFieldLabel = uilabel(app.Panel);
            app.AngleEditFieldLabel.HorizontalAlignment = 'right';
            app.AngleEditFieldLabel.FontSize = 16;
            app.AngleEditFieldLabel.FontWeight = 'bold';
            app.AngleEditFieldLabel.Position = [11 92 50 22];
            app.AngleEditFieldLabel.Text = 'Angle';

            % Create AngleEditField
            app.AngleEditField = uieditfield(app.Panel, 'numeric');
            app.AngleEditField.HorizontalAlignment = 'center';
            app.AngleEditField.FontSize = 16;
            app.AngleEditField.Position = [76 84 42 38];
            app.AngleEditField.Value = 45;

            % Create rotateButton
            app.rotateButton = uibutton(app.Panel, 'push');
            app.rotateButton.ButtonPushedFcn = createCallbackFcn(app, @rotateButtonPushed, true);
            app.rotateButton.FontSize = 16;
            app.rotateButton.FontWeight = 'bold';
            app.rotateButton.Position = [154 81 105 45];
            app.rotateButton.Text = {'rotate'; ''};

            % Create Panel_2
            app.Panel_2 = uipanel(app.UIFigure);
            app.Panel_2.ForegroundColor = [0 0.4471 0.7412];
            app.Panel_2.Title = '空域滤波';
            app.Panel_2.BackgroundColor = [0.8 0.8 0.8];
            app.Panel_2.FontWeight = 'bold';
            app.Panel_2.Position = [635 42 274 224];

            % Create ImageAxes
            app.ImageAxes = uiaxes(app.UIFigure);
            title(app.ImageAxes, 'raw image')
            app.ImageAxes.XTick = [];
            app.ImageAxes.XTickLabel = {'[ ]'};
            app.ImageAxes.YTick = [];
            app.ImageAxes.Position = [15 325 275 243];

            % Create ImageAxes_rotate
            app.ImageAxes_rotate = uiaxes(app.UIFigure);
            title(app.ImageAxes_rotate, 'After processing')
            app.ImageAxes_rotate.XTick = [];
            app.ImageAxes_rotate.XTickLabel = {'[ ]'};
            app.ImageAxes_rotate.YTick = [];
            app.ImageAxes_rotate.Position = [321 325 280 243];

            % Create ImageAxes_denoise
            app.ImageAxes_denoise = uiaxes(app.UIFigure);
            title(app.ImageAxes_denoise, 'denoise')
            app.ImageAxes_denoise.XTick = [];
            app.ImageAxes_denoise.XTickLabel = {'[ ]'};
            app.ImageAxes_denoise.YTick = [];
            app.ImageAxes_denoise.Position = [632 325 280 243];

            % Show the figure after all components are created
            app.UIFigure.Visible = 'on';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = app1_exported

            % Create UIFigure and components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.UIFigure)

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.UIFigure)
        end
    end
end